﻿using EventHub.Users;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Identity;
using Volo.Abp.Users;

namespace EventHub.Events.Registrations {
    public class EventRegistrationAppService(
        EventRegistrationManager eventRegistrationManager,
        IUserRepository userRepository,
        IEventRepository eventRepository,
        IEventRegistrationRepository eventRegistrationRepository,
        EventRegistrationNotifier eventRegistrationNotifier) : EventHubAppService, IEventRegistrationAppService {
        [Authorize]
        public async Task RegisterAsync(Guid eventId) {
            var @event = await eventRepository.GetAsync(eventId);
            var user = await userRepository.GetAsync(CurrentUser.GetId());

            await eventRegistrationManager.RegisterAsync(@event, user);

            await eventRegistrationNotifier.NotifyAsync(@event, user);
        }

        [Authorize]
        public async Task UnregisterAsync(Guid eventId) {
            await eventRegistrationManager.UnregisterAsync(
                await eventRepository.GetAsync(eventId),
                await userRepository.GetAsync(CurrentUser.GetId())
            );
        }

        [Authorize]
        public async Task<bool> IsRegisteredAsync(Guid eventId) {
            return await eventRegistrationManager.IsRegisteredAsync(
                await eventRepository.GetAsync(eventId),
                await userRepository.GetAsync(CurrentUser.GetId())
            );
        }

        public async Task<PagedResultDto<EventAttendeeDto>> GetAttendeesAsync(Guid eventId) {
            var eventRegistrationQueryable = await eventRegistrationRepository.GetQueryableAsync();
            var userQueryable = await userRepository.GetQueryableAsync();

            var query = from eventRegistration in eventRegistrationQueryable
                        join user in userQueryable on eventRegistration.UserId equals user.Id
                        where eventRegistration.EventId == eventId
                        orderby eventRegistration.CreationTime descending
                        select user;

            var totalCount = await AsyncExecuter.CountAsync(query);
            var users = await AsyncExecuter.ToListAsync(query.Take(10));

            return new PagedResultDto<EventAttendeeDto>(
                totalCount,
                ObjectMapper.Map<List<IdentityUser>, List<EventAttendeeDto>>(users)
            );
        }

        public async Task<bool> IsPastEventAsync(Guid eventId) {
            var @event = await eventRepository.GetAsync(eventId);

            return eventRegistrationManager.IsPastEvent(@event);
        }
    }
}
